/*jshint esversion: 6 */

// http://gallery.echartsjs.com/editor.html?c=xSkFFABj0e

// function update_chart(dom, data_file, provinces = null) {
function update_chart(chart, data_file, provinces = null) {
    $.get(data_file).success((content) => {
        let option_data = content_to_option(content, provinces);
        // let chart = echarts.init(dom);
        set_chart_option(chart, option_data);
    });
}
function content_to_option(content, provinces = null) {
    let lines = content.split('\n').filter((line) => {
        // return line.trim().length > 0;
        line = line.trim();
        if (line.length < 1) {
            // blank line
            return false;
        }
        if (line[0] == '#') {
            // comments line
            return false;
        }
        return true;
    });
    let title = lines[0].replace(/\s+/g, "");
    let legends = lines[1].split('\t').slice(1).map((e) => e.replace(/\s+|\"+/g, ""));
    // legends = legends.slice(0, 3);
    let data = lines.slice(2).map((line) => {
        nv = line.split('\t');
        let name = nv[0].replace(/\s+/g, "");
        // console.log(name);
        if (provinces != null) {
            if (provinces.includes(name) == false) {
                // console.log('remove');
                return null;
            }
        }
        return {
            name: nv[0].replace(/\s+/g, ""),
            values: nv.slice(1).map((e) => parseInt(e.replace(/\s+/g, ""))),
        };
    });
    data = data.filter((e) => e != null);
    // console.log(data);
    return data_to_option(title, legends, data);
}
// TODO: show subtotal of each legend with a bar/pie
function data_to_option(title, legends, data) {
    function NumDescSort(a, b) {
        return a.value - b.value;
    }
    function add(a, b) {
        return a + b;
    }
    function sum(list) {
        return list.reduce(add, 0);
    }
    function stat_values(values) {
        let stat = {
            min: Math.min(...values.map((e) => e.value)),
            max: Math.max(...values.map((e) => e.value)),
            // sum: sum(values.map((e) => e.value)),
            sum: sum(values.map((e) => e.value)).toFixed(2),
        };
        // stat.average = parseFloat((stat.sum / values.length).toFixed(2));
        return stat;
    }
    let resultdata = [];
    let legends2 = [];
    legends.forEach((legend, legend_idx) => {
        let legend_parent = legend.replace(/:.*/g, '');
        legends2.push(legend_parent);
        let values = data.map((row) => {
            return {
                name: row.name,
                value: row.values[legend_idx]
            };
        });
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max
        let stat = stat_values(values);
        let d = {
            name: legend_parent,
            value: values,
            min: stat.min,
            max: stat.max,
            sum: stat.sum,
            // average: stat.average,
        };
        d.value.sort(NumDescSort);
        // console.log(d);
        resultdata.push(d);

        if (legend.indexOf(':') >= 0) {
            let legend_a = legends[legend_idx].split(':');
            let parent = legend_a[0];
            let children_idx = legend_a[1].split(',').map((e) => parseInt(e));
            // console.log(children_idx);
            children_idx.forEach((child) => {
                // we already removed the first col of legends
                child -= 1;
                let legend2 = legends[child] + '/' + parent + 'x100';
                legends2.push(legend2);
                let values2 = data.map((row) => {
                    return {
                        name: row.name,
                        value: Math.round(row.values[child] / row.values[legend_idx] * 10000) / 100
                    };
                });
                // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/max
                // let min_value = Math.min(...values2.map((e) => e.value));
                // let max_value = Math.max(...values2.map((e) => e.value));
                let stat2 = stat_values(values2);
                let d2 = {
                    name: legend2,
                    value: values2,
                    // min: min_value,
                    // max: max_value,
                    min: stat2.min,
                    max: stat2.max,
                    sum: stat2.sum,
                    // average: stat2.average,
                };
                d2.value.sort(NumDescSort);
                // console.log(d2);
                resultdata.push(d2);
            });
        }
    });

    let option_data = {
        chart_title: title,
        legend: legends2,
        data: resultdata,
        title: legends2,
    };
    // console.log(option_data);
    return option_data;
}
function set_chart_option(chart, option_data) {
    let option = {
        title: [{
            text: option_data.chart_title,
            left: 'center'
        }, {
            // text: '总计: ' + option_data.data[0].sum + ', 平均：' + option_data.data[0].average,
            text: '总计: ' + option_data.data[0].sum,
            // right: 100,
            right: 150,
            top: 50,
            width: 100,
            textStyle: {
                color: '#000',
                fontSize: 14,
                align: 'center',
            }
        },],
        tooltip: {
            trigger: 'item'
        },
        legend: {
            orient: 'vertical',
            top: 100,
            left: 'left',
            selectedMode: 'single',
            data: option_data.legend,
        },
        visualMap: {
            // left: 'left',
            right: '40%',
            // top: 'bottom',
            // top: 'top',
            bottom: '30%',
            text: ['高', '低'],
            calculable: true,
            colorLightness: [0.2, 100],
            color: ['#c05050', '#e5cf0d', '#5ab1ef'],
            dimension: 0,
            min: option_data.data[0].min,
            max: option_data.data[0].max,
            range: [option_data.data[0].min, option_data.data[0].max],
        },
        toolbox: {
            show: true,
            orient: 'vertical',
            left: 'right',
            top: 'center',
            feature: {
                dataView: {
                    readOnly: false
                },
                restore: {},
                saveAsImage: {}
            }
        },
        grid: {
            right: 40,
            top: 100,
            bottom: 40,
            width: '30%'
        },
        xAxis: {
            position: 'top',
            type: 'value',
            boundaryGap: false,
            splitLine: {
                show: false
            },
            axisLine: {
                show: false
            },
            axisTick: {
                show: false
            },
            axisLabel: {
                show: false
            }
        },
        yAxis: {
            type: 'category',
            data: option_data.data[0].value.map((e) => e.name),
            axisTick: {
                alignWithLabel: true
            }
        },
        series: [],
    };
    // console.log(option_data.data);
    option_data.data.forEach((serie) => {
        option.series.push({
            z: 1,
            name: serie.name,
            type: 'map',
            map: 'china',
            left: '10',
            right: '30%',
            // top: 100,
            // bottom: "35%",
            top: 20,
            bottom: 20,
            zoom: 0.75,
            label: {
                normal: {
                    show: true
                },
                emphasis: {
                    show: false
                }
            },
            itemStyle: {
                normal: {
                    // color: 'red',
                },
                emphasis: {
                    color: "rgb(254,153,78)"
                }
            },
            // roam: 'scale',
            // roam: true,
            data: serie.value,
        });
        option.series.push({
            z: 2,
            name: serie.name,
            type: 'bar',
            // left: '90%',
            label: {
                normal: {
                    show: true,
                    align: 'right',
                    position: 'insideLeft',
                    offset: [100, 0],
                },
                emphasis: {
                    show: true,
                    align: 'right',
                    position: 'insideLeft',
                    offset: [100, 0],
                }
            },
            itemStyle: {
                emphasis: {
                    color: "rgb(254,153,78)"
                }
            },
            data: serie.value,
            markLine: {
                label: {
                    normal: {
                        formatter: '平均值: {c}'
                    }
                },
                lineStyle: {
                    normal: {
                        type: 'dashed'
                    }
                },
                data: [
                    {
                        name: '平均值',
                        // 支持 'average', 'min', 'max'
                        type: 'average'
                    }
                ],
                animation: false,
            }
        });
    });

    // console.log(option);
    chart.setOption(option);
    chart.on('legendselectchanged', function (params) {
        // console.log(chart.id + ':' + params.name);
        let idx = option_data.legend.indexOf(params.name);
        if (idx < 0) {
            console.log('invalid legend selected, something must be wrong');
            return;
        }
        // console.log(idx + '/' + option_data.data.length);
        // console.log();
        option.yAxis.data = option_data.data[idx].value.map((e) => e.name);
        option.visualMap.min = option_data.data[idx].min;
        option.visualMap.max = option_data.data[idx].max;
        option.visualMap.range = [option_data.data[idx].min, option_data.data[idx].max];
        // option.title[1].text = '总计: ' + option_data.data[idx].sum + ', 平均：' + option_data.data[idx].average;
        option.title[1].text = '总计: ' + option_data.data[idx].sum;
        chart.setOption(option);
    });
}

let all_provinces = `
北京
天津
河北
山西
内蒙古
辽宁
吉林
黑龙江
上海
江苏
浙江
安徽
福建
江西
山东
河南
湖北
湖南
广东
广西
海南
重庆
四川
贵州
云南
西藏
陕西
甘肃
青海
宁夏
新疆
`;
let app_data = {
    style: {
        chart: {
            width: 900,
            height: 700,
        }
    },
    // all_charts: all_files.split('\n').map((i) => i.trim()).filter((i) => i.length > 0).map((e, idx) => { return { id: idx, name: e, selected: false }; }),
    charts_order: [],
    key: '',
    all_provinces: all_provinces.split('\n').map((i) => i.trim()).filter((i) => i.length > 0).map((e, idx) => { return { name: e, selected: true }; }),
    echarts: [],
};
// all_files are defined in data_files.js
app_data.all_charts = all_files.split('\n')
    .map((i) => i.trim())
    .filter((i) => i.length > 0)
    .map((e, idx) => {
        let a = e.split('\t');
        return { id: idx, name: a[0], title: a[1], selected: false };
    });
app_data.charts_order = app_data.all_charts.map((e) => {
    return e.id;
});

let app = new Vue({
    delimiters: ['${', '}'],
    'el': '#app',
    data: app_data,
    computed: {
        chart_style: function () {
            return 'width: ' + this.style.chart.width + 'px;height: ' + this.style.chart.height + 'px;';
        },
        filtered_charts: function () {
            return this.all_charts.filter((c) => {
                return c.name.toLowerCase().search(this.key.toLowerCase()) >= 0;
            });
        },
        selected_charts: function () {
            return this.charts_order.filter((id) => {
                return this.all_charts[id].selected == true;
            }).map((id) => {
                return this.all_charts[id];
            });
        },
        selected_provinces: function () {
            return this.all_provinces.filter((p) => {
                return p.selected == true;
            }).map((p) => p.name);
        }
    },
    watch: {
        selected_charts: function () {
            this.update_charts();
        },
        selected_provinces: function () {
            this.update_charts();
        }
    },
    methods: {
        update_charts: function () {
            while (this.echarts.length > 0) {
                // console.log(this.echarts.length);
                this.echarts.pop().dispose();
            }
            this.selected_charts.forEach((c) => {
                // console.log(c.name);
                Vue.nextTick(() => {
                    // update_chart(document.getElementById('c_' + c.id), c.name, this.selected_provinces);
                    let chart = echarts.init(document.getElementById('c_' + c.id));
                    update_chart(chart, c.name, this.selected_provinces);
                    this.echarts.push(chart);
                });
            });
        },
        update_charts_order: function (sorted_list) {
            while (this.charts_order.length > 0) {
                this.charts_order.pop();
            }
            sorted_list.forEach((li) => {
                this.charts_order.push(li);
            });
        },
        select_provinces: function (type) {
            if (type == 'all') {
                this.all_provinces.forEach((p) => p.selected = true);
            } else if (type == 'reverse') {
                if (this.selected_provinces.length == this.all_provinces.length) {
                    // all provinces are selected, a reverse will cause none selected!
                    return;
                }
                this.all_provinces.forEach((p) => p.selected = p.selected ? false : true);
            }
        }
    }
});
$("#charts_order").sortable({
    update: function (event, ui) {
        let int = /[0-9]+/;
        let sorted_list = $('#' + event.target.id).sortable("toArray").map(
            (i) => {
                return parseInt(int.exec(i)[0]);
            }
        );
        app.update_charts_order(sorted_list);
    }
}).disableSelection();
$("#charts_order").draggable();

Vue.nextTick(() => {
    app.filtered_charts[0].selected = true;
});
